﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LCA.Community.Web.Filters;
using LCA.Community.DAL.Model;
using Microsoft.Practices.Unity;
using LCA.Community.DAL.Interfaces;
using LCA.Community.Web.WindowsLive;
using LCA.Community.Web.Models;
using System.IO;

namespace LCA.Community.Web.Controllers
{
    public class UserController : BaseController
    {
        #region Constants
        private readonly string LOGINCOOKIE = "webauthtoken";
        private const string OFFERS = "Profiles.Read";
        private static readonly DateTime expireCookie = DateTime.Now.AddYears(-10);
        #endregion

        #region Constructors
        public UserController()
            :base()
        {

        } 
        #endregion

        #region Actions
        /// <summary>
        /// Action for showing the user home page.
        /// </summary>
        /// <param name="id">The user id.</param>
        /// <returns>View of the user home page.</returns>
        [SecurityFilter(SecurityRequisites="Registered",ErrorResource="NotLoggedIn")]
        public ActionResult Index(string id)
        {
            User user = UsersRepository.Get(id);
            ViewData["friends"] = IsFriend(id);
            ViewData["owner"] = IsOwner(id);
            ViewData["name"] = id;

            var userModelView = MvcApplication.Container.Resolve<UserViewModel>(new ParameterOverrides { { "user", user} } );
            return View("Index", userModelView);
        }

        /// <summary>
        /// Action for seeing the policies of the web page.
        /// </summary>
        /// <returns>View of the policies of the web page.</returns>
        public ActionResult Policy()
        {
            return View();
        }

        /// <summary>
        /// Action for registering a new user
        /// </summary>
        /// <returns>View for registering a new user.</returns>
        public ActionResult Register()
        {
            WindowsLiveLogin wl_login = new WindowsLiveLogin(true);
            ViewData["lfxurl"] = wl_login.GetConsentUrl(OFFERS);
            ViewData["hospitals"] = HospitalsRepository.Entities;
            return View(new User());
        }

        /// <summary>
        /// Action for registering a new user
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns>If the user could be added returns the user home page, otherwise returns the view for creating a user.</returns>
        [ValidateInput(false)]
        [HttpPost]
        public ActionResult Register(User user)
        {
            user.PartitionKey = user.RowKey;
            user.Avatar = AvatarManager.GetUserAvatarUrl(user.RowKey,Request,Url);
            user.LiveID = Session["WLID"] as string;

            if (ModelState.IsValid)
            {
                if (UsersRepository.Get(user.RowKey) != null)
                {
                    ModelState.AddModelError("Alias", "El nombre de usuario ya está en uso.");
                    user.RowKey = String.Empty;
                }
                else
                {
                    UsersRepository.Add(user);

                    SaveUserInfo(user);
                    AvatarManager.SaveUserAvatar(user.RowKey,Request);

                    return RedirectToAction("Index", "Home");
                }
            }

            ViewData["hospitals"] = HospitalsRepository.Entities;
            return View(user);
        }

        /// <summary>
        /// Action for logging out.
        /// </summary>
        /// <returns>Redirect to the homre page.</returns>
        public ActionResult Logout()
        {
            DeleteUserInfo();

            // Windows Live ID logout...
            HttpCookie loginCookie = new HttpCookie("webauthtoken");
            loginCookie.Expires = expireCookie;
            Response.Cookies.Add(loginCookie);
            return RedirectToAction("Index", "Home");
        }

        /// <summary>
        /// Action for authenticate using Windows Live
        /// </summary>
        /// <returns>If the user is not registered return the view for registering the user, otherwise redirects to the home page.</returns>
        public ActionResult WindowsLiveAuthenticate()
        {
            WindowsLiveLogin windowsLiveID = new WindowsLiveLogin(true);
            HttpRequestBase request = HttpContext.Request;
            HttpResponseBase response = HttpContext.Response;

            string action = request["action"] ?? "";

            switch (action)
            {
                case "logout":
                    {
                        HttpCookie loginCookie = new HttpCookie(LOGINCOOKIE);
                        loginCookie.Expires = expireCookie;
                        response.Cookies.Add(loginCookie);

                        return RedirectToAction("Logout");
                    }
                case "clearcookie":
                    {
                        Session.Abandon();
                        string type;
                        byte[] content;
                        windowsLiveID.GetClearCookieResponse(out type, out content);
                        response.ContentType = type;
                        response.OutputStream.Write(content, 0, content.Length);
                        response.End();

                        return new EmptyResult();
                    }
                case "delauth":
                    {
                        WindowsLiveLogin wl_login = new WindowsLiveLogin(true);
                        WindowsLiveLogin.ConsentToken ConsentToken = wl_login.ProcessConsent(Request.Form);
                        string DelegationToken = ConsentToken.DelegationToken;
                        return RedirectToAction("RegisterFromLive", new { delToken = DelegationToken });
                    }
                case "login":
                    {
                        WindowsLiveLogin.User wllUser = windowsLiveID.ProcessLogin(request.Form);
                        Session.Add("WLID", wllUser.Id);
                        User user = UsersRepository.GetUserByLiveID(wllUser.Id);

                        if (user == null)
                        {
                            return RedirectToAction("Register", "User");
                        }

                        SaveUserInfo(user);
                        return RedirectToAction("Index", "Home");
                    }
                default:
                    return RedirectToAction("Index", "Home");
            }
        }

        /// <summary>
        /// Action for showing the groups that the user is subscribed to.
        /// </summary>
        /// <param name="id">The user id.</param>
        /// <returns>View showing the groups that the user is subscribed to.</returns>
        [SecurityFilter(SecurityRequisites = "Registered", ErrorResource = "NotLoggedIn")]
        public ActionResult Groups(string id)
        {
            var user = UsersRepository.Get(id);
            var userViewModel = MvcApplication.Container.Resolve<UserViewModel>(new ParameterOverrides { { "user", user} } );

            ViewData["friends"] = IsFriend(UserID);
            ViewData["owner"] = IsOwner(UserID);
            ViewData["username"] = UserID;
            return View("Groups", userViewModel);
        }

        /// <summary>
        /// Action fo editing user's profile
        /// </summary>
        /// <returns>View for editing user's profile.</returns>
        [SecurityFilter(SecurityRequisites = "Registered", ErrorResource = "NotLoggedIn")]
        public ActionResult Edit()
        {
            var userId = Session["ID"].ToString();
            User user = UsersRepository.Get(userId);
            ViewData["friends"] = IsFriend(UserID);
            ViewData["owner"] = IsOwner(UserID);
            ViewData["hospitals"] = HospitalsRepository.Entities;
            ViewData["userHospital"] = HospitalsRepository.GetHospitalOfUser(userId);
            return View("Edit", user);
        }

        /// <summary>
        /// Action for editing user's profile
        /// </summary>
        /// <returns>If the user's profile could be update it returns to the home page, otherwise it returns to the view for editing user's profile.</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [SecurityFilter(SecurityRequisites = "Registered", ErrorResource = "NotLoggedIn")]
        public ActionResult Edit(User user)
        {
            if (ModelState.IsValid)
            {
                user.RowKey = Session["ID"].ToString();
                user.PartitionKey = Session["ID"].ToString();
                user.LiveID = Session["WLID"] as string;

                SaveUserInfo(user);
                if (AvatarManager.HasAvatar(Request))
                {
                    user.Avatar = AvatarManager.GetUserAvatarUrl(user.RowKey, Request, Url);
                    AvatarManager.SaveUserAvatar(user.RowKey, Request);
                }

                UsersRepository.Update(user);
                return RedirectToAction("Index", "Home");
            }

            ViewData["friends"] = IsFriend(UserID);
            ViewData["owner"] = IsOwner(UserID);
            ViewData["hospitals"] = HospitalsRepository.Entities;
            ViewData["userHospital"] = HospitalsRepository.GetHospitalOfUser(UserID);
            return View("Edit", user);
        }


        /// <summary>
        /// Action for seeing the profile of the user.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <returns>View showing the profile of the user.</returns>
        [SecurityFilter(SecurityRequisites = "Registered", ErrorResource = "NotLoggedIn")]
        public ActionResult Profile(string id)
        {
            User user = UsersRepository.Get(id);
            ViewData["friends"] = IsFriend(id);
            ViewData["owner"] = IsOwner(id);
            ViewData["username"] = id;
            return View("Profile", user);
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Saves the user info to the session.
        /// </summary>
        /// <param name="user">The user.</param>
        private void SaveUserInfo(User user)
        {   
            var cookie = new HttpCookie("UserInfo");
            cookie["Name"] = user.FirstName;
            cookie["Alias"] = user.Alias;
            Session["ID"] = user.RowKey;
            cookie["HURL"] = user.HospitalUrl;
            cookie["SessionID"] = Session.SessionID;
            cookie.Expires = DateTime.Now.AddYears(10);

            HttpContext.Response.SetCookie(cookie);
        }

        /// <summary>
        /// Deletes the user info from the session.
        /// </summary>
        private void DeleteUserInfo()
        {
            HttpContext.Response.Cookies["UserInfo"].Expires = expireCookie;
            Session.Clear();
            Session.Abandon();
        }
        #endregion

        #region Dependencies
        [Dependency]
        public IUsersRepository UsersRepository { get; set; }
        [Dependency]
        public IHospitalsRepository HospitalsRepository { get; set; }
        [Dependency]
        public AvatarManager AvatarManager { get; set; }
        #endregion
    }
}
